from os.path import basename

from xml.dom import minidom

import gtk
from sheet import Sheet
from cell import Cell
from widgetOrganizer import WidgetOrganizer


class Worksheet(Sheet, gtk.ScrolledWindow):
    '''
    A Worksheet can hold an arbitraire amount of cells. It
    is, amongs others, responsible for completing the DOM representation.
    '''
    
    def __init__(self, ancestor, DOM=None, path=''):
        gtk.ScrolledWindow.__init__(self)
        Sheet.__init__(self, 'Worksheet', ancestor, path)
        
        self.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
        
        self.xmlTag = 'worksheet'
        self.namespace = {} #all cells of one worksheet share the local namespace
        self.ID_count = 0
        
        #create VBox-widget
        self._createVBox(DOM)
        self.setChanged(False)
        
    def _createVBox(self, DOM):        
        self.VBox = gtk.VBox()
        self.VBox.show()
        self.add_with_viewport(self.VBox)
        
        #create cellAdder at the end, enabling adding cells per double-click
        cellAdder = CellAdder(self)
        self.addChild(cellAdder)
        self.VBox.pack_start(cellAdder, expand=True)
        
        if DOM:
            cells = DOM.getElementsByTagName('cell')
            for cellDOM in cells:
                self.addCell(DOM=cellDOM)
        else:
            self.addCell()
    
    def addCell(self, DOM=None, neighbor=None, relPos=0):
        '''
        Creates a new cell above the neighbor or if not given,
        at the end of the worksheet.
        ''' 
        
        cell = Cell(self, DOM)
        cellAdder = CellAdder(self)
     
        if neighbor:
            pos = self.children.index(neighbor)+relPos
        else:
            pos = len(self.children)-1
        
        self.addChild(cell, pos)
        self.VBox.pack_start(cell, expand=False)
        self.VBox.reorder_child(cell, pos)
        
        self.addChild(cellAdder, pos)
        self.VBox.pack_start(cellAdder, expand=False)
        self.VBox.reorder_child(cellAdder, pos)
        
        self.set_focus_child(self.children[pos+1])
        self.focusAt(self.children[pos+1])
        
        self.changed = True
    
    def closeCell(self, appendant):
        '''
        Closes a cell and the appendant CellAdder
        '''

        pos = self.children.index(appendant)
        if type(appendant) is Cell:
            pos -= 1       
        self.removeChild(self.children[pos])
        self.removeChild(self.children[pos])
        self.changed = True
    
    def nextID(self):
        '''
        Every Input in a worksheet gets a unique ID.
        '''
        
        self.ID_count+=1
        return self.ID_count
        
    def focusAt(self, cell, relativePosition=0, cursorPosition=0):
        '''
        Set's the Focus at the cell relative to the given cell and places the cursor
        at the cursorPosition.
        '''
        
        assert cell in self.children
        cellPos = self.children.index(cell)
        pos = cellPos+2*relativePosition
        if len(self.children)-1<pos or 0>pos:
            return
        self.children[pos].getChildren('Input').placeCursor(charPos=cursorPosition)


class CellAdder(WidgetOrganizer, gtk.EventBox):
    '''
    A gtk.EventBox that enables the user to add new cells through
    double-click on a CellAdder
    '''
    
    def __init__(self, ancestor):
        gtk.EventBox.__init__(self)
        WidgetOrganizer.__init__(self, 'CellAdder', ancestor)
        
        self.connect('button_press_event', self._event_addCell)
        self.connect('enter-notify-event', self._event_mouseEnter)
        self.connect('leave-notify-event', self._event_mouseLeave)
        
        #A label to show on the evnt adder
        l = gtk.Label('_________')
        l.show()
        self.add(l)
    
    def _event_mouseEnter(self, widget, event):
        '''
        Changes the curser when it is over the CellAdder
        '''
        
        cursor = gtk.gdk.PLUS
        gtk.gdk.Window.set_cursor(self.window, gtk.gdk.Cursor(gtk.gdk.PLUS))
        
    def _event_mouseLeave(self, widget, event):
        '''
        Changes the curser back when it leaves the CellAdder
        '''
        
        cursor = gtk.gdk.ARROW
        gtk.gdk.Window.set_cursor(self.window, gtk.gdk.Cursor(gtk.gdk.ARROW))
    
    def _event_addCell(self, widget, event):
        '''
        Creates a new Cell if the user double-clicks the CellAdder
        '''
        if event.type==gtk.gdk._2BUTTON_PRESS:
            self.ancestor.addCell(neighbor=self)
